<!-- 服务器控制台页面 -->
<template>
    <div class="content" id="peszs">
        <n-grid cols="1 800:3" :x-gap="10" :y-gap="5">
            <n-grid-item>
                <n-grid cols="1 400:2" :x-gap="10" :y-gap="10">
                    <n-grid-item>
                        <!-- 其他信息 -->
                        <div class="Other">
                            <n-h4 prefix="bar">
                                服务器信息
                            </n-h4>
                            <!-- 服务器信息显示 -->
                            <div class="serverInfo">
                                <div>
                                    <i class="iconfont icon-bianji0"></i>
                                    名称：{{ serveInfo.name }}
                                </div>
                                <div>
                                    <i class="iconfont"
                                        :class="serveInfo.isRun ? 'icon-running green' : 'icon-yitingzhi red'"></i>
                                    状态：<span :class="serveInfo.isRun ? 'green' : 'red'">{{ serveInfo.isRun ? '运行中' : '未运行'
                                    }}</span>
                                </div>
                                <div>
                                    <i class="iconfont icon-computer"></i>
                                    类型：{{ serveInfo.type }}
                                </div>
                                <div>
                                    <i class="iconfont icon-gerenxinxi"></i>
                                    创建日期：{{ formatTimestamp(serveInfo.createTime) }}
                                </div>
                                <div>UUID: <span class="f10">{{ serveInfo.uuid }}</span></div>

                            </div>
                        </div>
                    </n-grid-item>

                    <n-grid-item>
                        <!-- 服务器控制 -->
                        <div class="Other">
                            <n-h4 prefix="bar">
                                服务器控制
                            </n-h4>
                            <!-- 服务器控制按钮 -->
                            <n-button-group vertical>
                                <n-button ghost @click="run" :type="serveInfo.isRun ? 'error' : 'success'">
                                    <template #icon>
                                        <i class="iconfont"
                                            :class="serveInfo.isRun ? 'icon-yitingzhi' : 'icon-running'"></i>
                                    </template>
                                    {{ serveInfo.isRun ? '停止' : '启动' }}
                                </n-button>
                                <n-button type="warning" ghost @click="restart" :disabled="!serveInfo.isRun">
                                    <template #icon>
                                        <i class="iconfont icon-reset"></i>
                                    </template>
                                    重启
                                </n-button>

                                <n-popconfirm @positive-click="closeServe" negative-text="取消" positive-text="强制停止">
                                    <template #trigger>
                                        <n-button type="error" ghost :disabled="!serveInfo.isRun">
                                            <template #icon>
                                                <i class="iconfont icon-power"></i>
                                            </template>
                                            强制结束
                                        </n-button>
                                    </template>
                                    你确定要执行该操作吗？
                                </n-popconfirm>

                            </n-button-group>
                        </div>
                    </n-grid-item>

                    <n-grid-item span="1 400:2">
                        <!-- 服务器功能 -->
                        <div class="Other">
                            <n-h4 prefix="bar">
                                服务器功能
                            </n-h4>
                            <!-- 服务器功能按钮 -->
                            <n-button-group vertical>
                                <n-button ghost @click="showProperties">
                                    <template #icon>
                                        <i class="iconfont icon-peizhiip"></i>
                                    </template>
                                    服务器配置文件
                                </n-button>
                                <n-button-group>
                                    <n-button style="flex: 1;" @click="showTel">
                                        <template #icon>
                                            <i class="iconfont icon-config-command"></i>
                                        </template>
                                        终端设置
                                    </n-button>
                                    <n-button style="flex: 1;" disabled>
                                        <template #icon>
                                            <i class="iconfont icon-CPU"></i>
                                        </template>
                                        监听配置
                                    </n-button>
                                </n-button-group>
                                <!-- <n-button-group>
                                    <n-button style="flex: 1;">
                                        <template #icon>
                                            <i class="iconfont icon-yitingzhi"></i>
                                        </template>
                                        再吃
                                    </n-button>
                                    <n-button style="flex: 1;">
                                        <template #icon>
                                            <i class="iconfont icon-yitingzhi"></i>
                                        </template>
                                        一颗
                                    </n-button>
                                </n-button-group> -->
                                <n-button ghost @click="explorerCatalog">
                                    <template #icon>
                                        <i class="iconfont icon-ziyuan"></i>
                                    </template>
                                    打开服务器文件夹
                                </n-button>
                            </n-button-group>
                        </div>
                    </n-grid-item>
                </n-grid>
            </n-grid-item>
            <n-grid-item span="800:2">
                <!-- 控制台 -->
                <div class="console">
                    <n-space vertical>
                        <n-h4 prefix="bar">
                            控制台
                        </n-h4>
                        <!-- 控制台 -->
                        <div class="cmd" ref="terminalContainer"></div>
                        <!-- 输入框 -->
                        <n-auto-complete v-model:value="cmdValue" :disabled="!serveInfo.isRun" :input-props="{
                            autocomplete: 'disabled'
                        }" :options="options" placeholder="此处输入命令，回车键即可执行" :render-label="renderLabel"
                            @keydown.native.enter="writeProcess" @keydown.up="handleUpKey" @keydown.down="handleDownKey">
                            <template #prefix>
                                <i class="iconfont icon-config-command"></i>
                            </template>
                        </n-auto-complete>
                    </n-space>
                </div>
            </n-grid-item>

        </n-grid>

    </div>

    <!-- 服务器配置文件修改 -->
    <n-drawer v-model:show="active" default-width="70%" placement="right" :resizable="false" to="#peszs">
        <n-drawer-content>
            <template #header>
                服务器配置
                <n-radio-group v-model:value="showType" size="small" @update:value="showTypeupdate">
                    <n-radio-button v-for="(item, index) in guiSelectrList" :key="index" :value="item.value"
                        :label="item.name" :disabled="item.disabled" />
                </n-radio-group>
            </template>

            <div v-if="showType == 'gui'">
                <!-- 我的世界 bds配置gui -->
                <guiBds v-if="['minecraft-llbds', 'minecraft-bds'].includes(serveInfo.type)" :config="properties"
                    @result="writeProperties" />
                <!-- 铁锈战争 -->
                <guiRw v-if="['rw-rts'].includes(serveInfo.type)" :config="properties"
                    @result="writeProperties($event, 'json')" />
            </div>
            <div v-else-if="showType == 'edit'">
                <!-- 源码展示 -->
                <div style="margin: 0 0 20px;">
                    <n-button type="primary" size="small" @click="saveEdit">
                        <template #icon>
                            <i class="iconfont icon-zhengque"></i>
                        </template>
                        保存
                    </n-button>
                </div>
                <VueCodemirror v-model:modelValue="editText" :style="{ height: windowHeight + 'px' }" />
            </div>

        </n-drawer-content>
    </n-drawer>

    <!-- 终端配置 -->
    <n-drawer v-model:show="terminalActive" default-width="70%" placement="right" :resizable="false" to="#peszs">
        <n-drawer-content>
            <template #header>
                终端配置（路径均为相对路径）
            </template>
            <div style="margin: 0 0 20px;">
                <n-button type="primary" size="small" @click="saveConfigTel">
                    <template #icon>
                        <i class="iconfont icon-zhengque"></i>
                    </template>
                    保存
                </n-button>
            </div>
            <n-form ref="formRef" :model="serveInfoTel">
                <n-form-item label="名称（备注）" path="name" :rule="{
                    required: true,
                    message: '请输入名称',
                    trigger: ['input', 'blur']
                }">
                    <n-input v-model:value="serveInfoTel.name" placeholder="请输入名称" clearable>
                        <template #prefix>
                            <i class="iconfont icon-bianji0"></i>
                        </template>
                    </n-input>
                </n-form-item>

                <n-form-item label="启动命令（程序）" path="start" :rule="{
                    required: true,
                    message: '请输入启动命令',
                    trigger: ['input', 'blur']
                }">
                    <n-input v-model:value="serveInfoTel.start" placeholder="请输入启动命令" clearable>
                        <template #prefix>
                            <i class="iconfont icon-running"></i>
                        </template>
                    </n-input>
                </n-form-item>

                <n-form-item label="结束命令" path="stop" :rule="{
                    required: true,
                    message: '请输入结束命令',
                    trigger: ['input', 'blur']
                }">
                    <n-input v-model:value="serveInfoTel.stop" placeholder="请输入结束命令" clearable>
                        <template #prefix>
                            <i class="iconfont icon-power"></i>
                        </template>
                    </n-input>
                </n-form-item>

                <n-form-item label="配置文件路径" path="config" :rule="{
                    required: true,
                    message: '请输入配置文件路径',
                    trigger: ['input', 'blur']
                }">
                    <n-input v-model:value="serveInfoTel.config" placeholder="请输入配置文件路径" clearable>
                        <template #prefix>
                            <i class="iconfont icon-peishushuju"></i>
                        </template>
                    </n-input>
                </n-form-item>

                <n-form-item label="控制台编码" path="coding" :rule="{
                    required: true,
                    message: '请输入控制台编码',
                    trigger: ['input', 'blur']
                }">
                    <template #label>
                        <i class="iconfont icon-navicon-bmfa"></i>
                        控制台编码
                    </template>

                    <n-select v-model:value="serveInfoTel.coding" label-field="value" :options="toolStore.codingOptions"
                        placeholder="请选择控制台编码" />
                    <!-- <n-input v-model:value="serveInfoTel.coding" placeholder="请输入控制台编码" clearable>
                        <template #prefix>
                            <i class="iconfont icon-navicon-bmfa"></i>
                        </template>
                    </n-input> -->
                </n-form-item>




                <n-form-item path="type" label="服务器类型" :rule="{
                    required: true,
                    message: '请选择服务器类型',
                    trigger: ['change']
                }">
                    <template #label>
                        <i class="iconfont icon-shanglou"></i>
                        服务器类型
                    </template>
                    <n-select v-model:value="serveInfoTel.type" :options="serverTypeOptions" placeholder="请选择服务器类型" />
                </n-form-item>

                <n-form-item label="服务器自启（软件启动时）" path="autorun" :rule="{
                    required: true
                }">
                    <n-switch v-model:value="serveInfoTel.autorun">
                        <template #checked>
                            已打开服务器自启
                        </template>
                        <template #unchecked>
                            已关闭服务器自启
                        </template>
                    </n-switch>
                </n-form-item>



            </n-form>

        </n-drawer-content>
    </n-drawer>
</template>
  
  
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, computed, toRaw, nextTick } from "vue";
import { useMainStore, useToolStore } from "@renderer/store/index";
import { useRouter, useRoute } from 'vue-router';
import guiBds from '@renderer/components/gui-bds.vue';
import guiRw from '@renderer/components/gui-rw.vue';
import { getHintCmd } from '@renderer/assets/common/api';
const toolStore = useToolStore();
const route = useRoute();
// 组件
import "xterm/css/xterm.css";
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { useMessage } from "naive-ui";

const message = useMessage();


const active = ref(false);//服务器配置文件抽屉
const terminalActive = ref(false);//终端配置抽屉
const writeArr = ref({ arr: [], index: 0 });//当前控制台输入的命令列表

const guiList = ['minecraft-bds', 'minecraft-llbds', 'rw-rts'];//支持gui视图的列表 其他类型未支持

const showType = ref('gui');//服务器配置文件展示（gui/edit）
const guiSelectrList = reactive([
    { name: '视图', value: 'gui', disabled: false },
    { name: '源码', value: 'edit', disabled: false }
]);

const serverTypeOptions = reactive(toolStore.serverTypeOptions.filter(v => v.value != 'sharePack'));

let cmdValue = ref('');//命令的变量
const formRef = ref(null);//终端配置的表单对象
const terminalContainer = ref(null);

let serveInfo = reactive({});//当前服务器信息
let serveInfoTel = reactive({});//当前服务器信息(终端)

let properties = reactive({});//服务器配置信息gui的
let editText = ref('');//edit编辑器配置文件的内容

const terminal = new Terminal({
    // 渲染类型
    rendererType: 'canvas',
    rows: 35,
    cols: 92,
    fontSize: 12,
    // 光标闪烁
    cursorBlink: false,
    //   是否禁用输入
    disableStdin: true,
    scrollback: 800, //回滚
    tabStopWidth: 8, //制表宽度
    cursorStyle: 'underline',
    lineWrapping: false,//禁止自动换行
    screenKeys: true,
    drawBoldTextInBrightColors: true,
    theme: {
        //   字体
        foreground: '#ffffff',
        background: '#353d44',
        // 光标
        cursor: 'help',
        lineHeight: 12,
    },
});

const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);

terminal.onKey(e => {
    // console.log(e);
    //ctrol+ c copy
    if (e.key == '\x03' && terminal.hasSelection()) {
        navigator.clipboard.writeText(terminal.getSelection())
    }
});


let options = computed(() => {
    let cmdArr = new Map(toolStore.consoleAutoHint?.hint[toolStore.consoleAutoHint?.type[serveInfo.type]]);
    cmdArr = Array.from(cmdArr);
    let prefix = cmdValue.value;

    let suggestions = cmdArr
        .filter(([key, illustrate]) => key.startsWith(prefix))
        .map(([key, illustrate]) => ({
            label: prefix + key.slice(prefix.length),
            value: key,
            illustrate
        }));

    return suggestions;
});


/**
 * 渲染标签
 * @param {*} option 
 */
function renderLabel(option) {
    return [option.label, ' - ', option.illustrate];
}

let { ipcRenderer } = window.electron;
let isRestart = false;//是否该重启
const windowHeight = ref(480);


// 监听窗口大小变化
ipcRenderer.on('update-win-size', (e, data) => {
    windowHeight.value = data[1] - 220;
});

nextTick(() => {
    // 挂载到元素
    try {
        terminal.open(terminalContainer.value);
    } catch (error) {
        console.error(error);
    }

    fitAddon.fit();//调整容器适合尺寸
});//等待渲染完成

onMounted(() => {


    // 读取控制台命令记录
    let consoleStr = sessionStorage.getItem(route.query.uuid + '_console');
    if (consoleStr) {
        try {
            let newData = JSON.parse(consoleStr);
            writeArr.value = newData;
        } catch (error) {
            console.error(error);
        }
    }

    /**
     * 获取控制台补全提示
     */
    getHintCmd().then(res => {
        toolStore.consoleAutoHint = res;
    });
    // terminal.scrollToBottom();//滚动到底部

    // terminal.clear();//清除屏幕

    //获取指定服务器的信息和运行情况
    window.api.getItemInfo(route.query.uuid).then(res => {
        console.log('服务器信息：', res);
        Object.assign(serveInfo, res);//设置服务器信息
        if (!guiList.includes(serveInfo.type)) {
            guiSelectrList[0].disabled = true;//没有gui
            showType.value = 'edit';//设置选中源码模式
        } else {
            guiSelectrList[0].disabled = false;//有gui
            showType.value = 'gui';//设置选中gui模式
        }

        // 获取控制台信息
        window.api.getLog(serveInfo.path).then(res2 => {
            terminal.writeln(res2);
            terminal.scrollToBottom();//滚动到底部
            fitAddon.fit();//调整容器适合尺寸
        });
    }).catch(err => {
        console.error(err);
    });



    // 监听控制台运行的日志
    ipcRenderer.on('console_data', (e, key, data) => {
        if (key != serveInfo.uuid) return;
        terminal.write(data);
        terminal.scrollToBottom();//滚动到底部
    });

    // 监听窗口大小变化
    ipcRenderer.on('update-win-size', (e, data) => {
        fitAddon.fit();//调整容器适合尺寸
        terminal.scrollToBottom();//滚动到底部
    });


    // 监听控制台停止运行
    ipcRenderer.on('console_close', (e, key) => {
        if (key == serveInfo.uuid) {
            serveInfo.isRun = false;
            if (isRestart) {
                // 是否重启标识
                isRestart = false;//还原标识
                run();//重新启动一下
            }

        }
    });

    // terminal.write(`你好朋友，请开启服务器！\r\n`);

    // setInterval(() => {
    //     // terminal.write(`${count}\r\n`);
    //     terminal.writeln(`${count}`);
    //     count++;
    // }, 100);

    // console.log('进入');
});


onBeforeUnmount(() => {
    // console.log('退出');
});

/**
 * 显示服务器配置设置的
 */
function showProperties() {
    if (serveInfo.config === '') {
        message.error('你并没有设置配置文件路径！');
        return;
    }
    if (showType.value == 'gui') {
        let newPrper = {};
        if (serveInfo.type == 'rw-rts') {
            newPrper = window.api.getJson([serveInfo.path, serveInfo.config]);
            console.log('读取：', newPrper);
        }
        if (['minecraft-llbds', 'minecraft-bds'].includes(serveInfo.type)) {
            newPrper = window.api.getProperties([serveInfo.path, serveInfo.config]);
        }

        properties = reactive(newPrper);
    } else {
        // edit
        editText.value = window.api.getFileText([serveInfo.path, serveInfo.config]);//获取文本配置内容
    }
    active.value = true;//显示抽屉
}
//视图和源码切换
function showTypeupdate(e) {
    if (e == 'gui') {
        let newPrper = window.api.getProperties([serveInfo.path, serveInfo.config]);
        Object.assign(properties, newPrper);
    } else {
        // edit
        editText.value = window.api.getFileText([serveInfo.path, serveInfo.config]);//获取文本配置内容
    }
}

/**
 * 显示终端配置设置的
 */
function showTel() {
    let newObj = JSON.parse(JSON.stringify(toRaw(serveInfo)));
    // 删除多余数据
    delete newObj['isRun'];
    delete newObj['path'];
    Object.assign(serveInfoTel, newObj);
    terminalActive.value = true;//显示抽屉
}


/**
 * 保存终端数据到配置
 */
function saveConfigTel() {
    formRef.value?.validate((errors) => {
        if (!errors) {
            message.success("保存成功");
            window.api.setJson([serveInfo.path, 'project-yoyo.json'], toRaw(serveInfoTel));
            //获取指定服务器的信息和运行情况(更新一下数据)
            window.api.getItemInfo(route.query.uuid).then(res => {
                Object.assign(serveInfo, res);//设置服务器信息
                if (!guiList.includes(serveInfo.type)) {
                    guiSelectrList[0].disabled = true;//没有gui
                    showType.value = 'edit';//设置选中源码模式
                } else {
                    guiSelectrList[0].disabled = false;//有gui
                    showType.value = 'gui';//设置选中gui模式
                }
            });
        } else {
            message.error("请填写正确！");
        }
    });
}

/**
 * 把gui修改的属性写入到配置
 * @param {object} obj 
 */
function writeProperties(obj, type = null) {
    if (type == 'json') {
        console.log('保存：', obj);
        window.api.setJson([serveInfo.path, serveInfo.config], obj);
        return;
    }
    window.api.setProperties([serveInfo.path, serveInfo.config], obj);
}
/**
 * 将edit的数据写入配置文件
 */
function saveEdit() {
    window.api.setFileText([serveInfo.path, serveInfo.config], editText.value);//获取文本配置内容
    message.success('保存成功！');
}

/**
 * 打开项目指定目录
 */
function explorerCatalog() {
    window.api.explorerCatalog(serveInfo.path).then(res => {
        if (!res) {
            message.error('打开失败！');
            return;
        }
    });
}

/**
 * 输入框按方向上
 * @param {*} e 
 */
function handleUpKey(e) {
    e.preventDefault();
    if (!(writeArr.value.index > 0)) return;
    writeArr.value.index--;
    let newArr = writeArr.value.arr;
    let cstr = newArr[writeArr.value.index];
    cmdValue.value = cstr;
}

/**
 * 输入框按方向下
 * @param {*} e 
 */
function handleDownKey(e) {
    e.preventDefault();
    if (!(writeArr.value.index < (writeArr.value.arr.length - 1))) return;
    writeArr.value.index++;
    let newArr = writeArr.value.arr;
    let cstr = newArr[writeArr.value.index];
    cmdValue.value = cstr;
}

/**
 * 向控制台发送信息
 */
function writeProcess() {
    terminal.writeln(cmdValue.value);
    // 加入到控制台缓存
    writeArr.value.arr.push(String(cmdValue.value).trim());
    let newStr = new Set(writeArr.value.arr);
    writeArr.value.arr = Array.from(newStr);
    writeArr.value.index = (writeArr.value.arr.length - 1);
    sessionStorage.setItem(route.query.uuid + '_console', JSON.stringify(writeArr.value));
    ipcRenderer.invoke('writeProcess', serveInfo.uuid, `${cmdValue.value}\n`, serveInfo.coding);
    terminal.scrollToBottom();//滚动到底部
    cmdValue.value = '';
}

/**
 * 强制关闭服务器
 */
function closeServe() {
    ipcRenderer.invoke('closeProcess', serveInfo.uuid);
}

/**
 * 重启服务器
 */
function restart() {
    if (serveInfo.stop === '') {
        message.error('你并没有设置停止命令！');
        return;
    }
    isRestart = true;//重启标识
    // 是运行状态 调用结束方法
    terminal.writeln(serveInfo.stop);
    ipcRenderer.invoke('writeProcess', serveInfo.uuid, `${serveInfo.stop}\n`, serveInfo.coding);
    terminal.scrollToBottom();//滚动到底部
}

/**
 * 运行(停止)服务器
 */
function run() {
    fitAddon.fit();//调整容器适合尺寸
    if (serveInfo.isRun) {
        // 是运行状态 调用结束方法
        if (serveInfo.stop === '') {
            message.error('你并没有设置停止命令！');
            return;
        }
        terminal.writeln(serveInfo.stop);
        ipcRenderer.invoke('writeProcess', serveInfo.uuid, `${serveInfo.stop}\n`, serveInfo.coding);
        terminal.scrollToBottom();//滚动到底部
        return;
    }
    if (serveInfo.start === '') {
        message.error('你并没有设置开始命令（程序）！');
        return;
    }


    const splitArgs = String(serveInfo.start).match(/[^\s]+/g);
    let runCmdAS = splitArgs[0];
    if (splitArgs.length > 1) {
        runCmdAS = Array.from(splitArgs);
    }
    //调用启动服务器
    ipcRenderer.invoke('createProcess', serveInfo.uuid, runCmdAS, serveInfo.path, serveInfo.coding ?? 'utf8').then(res => {
        if (!res) {
            message.error('启动失败！');
            return;
        }
        terminal.clear();//清除屏幕
        serveInfo.isRun = res;
    }).catch(err => {
        message.error('启动失败！', err.message);
    });
}



/**
 * 获取日期时间
 * @returns 
 */
function formatTimestamp(timestamp) {
    const date = new Date(timestamp);

    const year = date.getFullYear();
    const month = ("0" + (date.getMonth() + 1)).slice(-2);
    const day = ("0" + date.getDate()).slice(-2);

    const hours = ("0" + date.getHours()).slice(-2);
    const minutes = ("0" + date.getMinutes()).slice(-2);
    const seconds = ("0" + date.getSeconds()).slice(-2);

    const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;

    return formattedDate;
}


</script>
  
  
<style lang="scss" scoped>
.content {
    width: 100%;
    display: flex;
    flex-direction: row;

    .Other {
        padding: 10px;
        background-color: #fff;
        border-radius: 5px;
        display: flex;
        flex-direction: column;

        .redbg {
            background-color: rgba(255, 0, 0, 0.3);
        }

        .serverInfo {
            min-height: 102px;

            .f10 {
                font-size: 10px;
            }
        }

        .red {
            color: red !important;
        }

        .green {
            color: green !important;
        }
    }

    .console {
        padding: 10px;
        background-color: #fff;
        border-radius: 5px;
        display: flex;
        flex-direction: column;

    }
}
</style>